
from jwt.exceptions import DecodeError
from typing import List
from fastapi import Depends,APIRouter
from db.session import get_session
from schema.user import LoginParams, RegisterParams
from utils.encryAbout import get_password_hash, encode_token, verify_password, encode_data, decode_data
from model.user import User
from server.user import check_user_and_password, create_user, get_user_by_username, get_today_sign_in_log, get_user_by_id, get_gold_coins_logs
from server.goldCoins import invite_new_users_gold_coins_calculate, sign_in_gold_coins_calculate
from schema.response.baseResponse import CustomException, BaseResponse, PageResponse
from schema.response.userResponse import LoginResponse, UserResponse, GlodCoinsLogResponse, UserGoldLogResponse
from utils.middleware import decode_token_by_head




router = APIRouter(
    prefix="/user/v1",
    tags=["user"],
    dependencies=[],
    responses={404: {"description": "Not found"}}
)


@router.post("/login", response_model=BaseResponse[LoginResponse], summary="登录接口")
async def login(login_params: LoginParams):
    user: User = await check_user_and_password(login_params.username)
    if not user:
        raise CustomException(code=400, msg="用户名或密码错误")
    status: bool = verify_password(login_params.password, user.password)
    if not status:
        raise CustomException(code=400, msg="用户名或密码错误")
    token = encode_token({"username": user.username, "id": user.id, "gold_coins": user.gold_coins})
    # 判断今天有没有签到记录
    sign_in_today_info = await get_today_sign_in_log(user.id)
    user_dict = user.__dict__
    if sign_in_today_info:
        user_dict["sign_in"] = 1
    return BaseResponse.success(data=LoginResponse(token=token, user=UserResponse(**user_dict)))


@router.post("/register", response_model=BaseResponse[LoginResponse], description="注册接口,如果有邀请码的话, 会为源用户增加积分； 只能注册非超级管理用户", summary="注册接口")
async def register(register_params: RegisterParams):
    # 考虑后将整个作为一个事务所以采用传递， sqlalchemy 事务中只有最后一个commit 会生效
    if register_params.password != register_params.password_confirm:
        raise CustomException(code=400, msg="两次密码不一致")
    async with get_session() as db:
        user = await get_user_by_username(db, register_params.username)
        if user:
            raise CustomException(code=400, msg="用户名已存在")
        user = await create_user(db, register_params.username, get_password_hash(register_params.password))
        token = encode_token({"username": user.username, "id": user.id, "gold_coins": user.gold_coins})
        if register_params.invitaion_code:
            try:
                invitaion_code_info = decode_data(register_params.invitaion_code)
                source_user_id = invitaion_code_info.get("invitaion_code")
            except DecodeError as e:
                raise CustomException(400, "邀请码解析错误")
            # 邀请新用户注册获得积分(如果解析错误记下日志后边排查原因，以注册为主)
            await invite_new_users_gold_coins_calculate(db, source_user_id=source_user_id, target_user_id=user.id, target_user_name=user.username)
        return BaseResponse.success(data=LoginResponse(token=token, user=UserResponse(**user.__dict__)))


## 打卡赚取积分()
@router.post("/signin", response_model=BaseResponse[UserResponse], summary="打卡赚取积分")
async def sign_in(token: str = Depends(decode_token_by_head)):
    sign_in_today_info = await get_today_sign_in_log(token.get("id"))
    if sign_in_today_info:
        raise CustomException(code=400, msg="今天已经签到过了")
    else:
        await sign_in_gold_coins_calculate(source_user_id=token.get("id"), blog_id=None)
        user = await get_user_by_id(token.get("id"))
        user_dict = user.__dict__
        user_dict["sign_in"] = 1
        return BaseResponse.success(data=UserResponse(**user_dict))
    

@router.get("/invitaionCode", response_model=BaseResponse[str], summary="获取邀请码", description="这个邀请不是用户填写而是，用户通过分享页进行注册的时候自动填写")
async def get_invitaion_code(token: str = Depends(decode_token_by_head)):
    return BaseResponse.success(data=encode_data({"invitaion_code": token.get("id")}))


@router.get("/getGoldCoinsLogs", response_model=BaseResponse[PageResponse[List[UserGoldLogResponse]]], summary="获取积分记录")
async def get_gold_coins_log(page: int = 1, page_size: int = 15, gold_coins_id: int = None, token: str = Depends(decode_token_by_head)):
    gold_coins_logs_info: dict = await get_gold_coins_logs(token.get("id"), page=page, page_size=page_size, gold_coins_info_id=gold_coins_id)
    return BaseResponse.success(data=PageResponse(total=gold_coins_logs_info.get("total"), data=gold_coins_logs_info.get("gold_coins_logs")))